package org.qloudgen.borg.pages.provider;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.wicket.Page;
import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;

import org.qloudgen.borg.CommonValues;
import org.qloudgen.borg.beans.MenuNode;
import org.qloudgen.borg.beans.UserBean;
import org.qloudgen.borg.metadb.DefaultImpl;

import com.google.common.collect.Maps;

public class MenuProvider implements ITreeProvider<MenuNode>
{

    private static final long serialVersionUID = 1L;
    public List<MenuNode> nodes = new ArrayList<MenuNode>();

    @SuppressWarnings("unchecked")
	public MenuProvider() {
    	
    	String userNo = CommonValues.getUserNo();
    	
    	// get user info from metadb
    	UserBean user = DefaultImpl.getUserInfo(userNo);
    	
    	List<MenuNode> menuNodes = DefaultImpl.getMenunodes(user);
    	Map<String,MenuNode> map = Maps.newHashMap();
    	
    	// list to map
    	for (MenuNode menunode : menuNodes){
    		map.put(menunode.getId(),menunode);    		
    	}
    	
    	for (MenuNode menuNode : menuNodes){

			try {
				
				if (menuNode.getDbClass() != null && !menuNode.getDbClass().equals("")){
	    			menuNode.setPageClass((Class<? extends Page>) Class.forName(menuNode.getDbClass()));
				}
				
				if (menuNode.getDbParent().equals("0")){
	    			nodes.add(menuNode);
	    		} else {
	    			menuNode.setParent(map.get(menuNode.getDbParent()));
	    		}
				
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
    	}
    	
    }

    @Override
    public void detach() { }

    @Override
    public Iterator<MenuNode> getRoots()
    {
        return this.nodes.iterator();
    }

    @Override
    public boolean hasChildren(MenuNode menuNode)
    {
        return menuNode.getParent() == null || !menuNode.getChildren().isEmpty();
    }

    @Override
    public Iterator<MenuNode> getChildren(final MenuNode menuNode)
    {
        return menuNode.getChildren().iterator();
    }

    @Override
    public IModel<MenuNode> model(MenuNode menuNode)
    {
        return new NodeModel(menuNode);
    }

    private class NodeModel extends LoadableDetachableModel<MenuNode>
    {
        private static final long serialVersionUID = 1L;

        private final String id;

        public NodeModel(MenuNode menuNode)
        {
            super(menuNode);

            id = menuNode.getId();
        }

        @Override
        protected MenuNode load()
        {
            return getMenuNode(id);
        }

        @Override
        public boolean equals(Object obj)
        {
            if (obj instanceof NodeModel)
            {
                return ((NodeModel)obj).id.equals(id);
            }
            return false;
        }

        @Override
        public int hashCode()
        {
            return id.hashCode();
        }
        
        public MenuNode getMenuNode(String id)
        {
            return findMenuNode(nodes, id);
        }

        private MenuNode findMenuNode(List<MenuNode> nodes, String id)
        {
            for (MenuNode menuNode : nodes)
            {
                if (menuNode.getId().equals(id))
                {
                    return menuNode;
                }

                MenuNode temp = findMenuNode(menuNode.getChildren(), id);
                if (temp != null)
                {
                    return temp;
                }
            }

            return null;
        }
    }
}